// Tabel Pengambilan Mata Kuliah

#ifndef TABELPMK_H
#define TABELPMK_H

#include "..\TabelMK\TabelMK.h"
#include "..\TabelMhs\TabelMhs.h"
#include "..\TahunAkademik\TahunAkademik.h"

struct RECORD_PMK {
	AddressMhs Mhs; // <-- Key
	AddressMK MK; // <-- Key
	int semester; // <-- Key
	ThnAkademik T; // <-- Key
	char nilai;
	
	struct RECORD_PMK *next;
	ownerList _ownerList; // Di node mana saja Record ini di simpan?
};

typedef struct RECORD_PMK RecordPMK;

typedef RecordPMK* AddressPMK;

typedef AddressPMK TabelPMK;

// DEFINISI NAMA TABEL
#define NAMATABELPMK	CharToString("PengambilanMK")

// SELEKTOR
#define MHS(R)			(R)->Mhs
#define MK(R)			(R)->MK
#define SEMESTER(R)		(R)->semester
#define NILAI(R)		(R)->nilai
#define TAHUN(R)		(R)->T

#define TABELPMK_NUM_KOLOM	5

// DEFINISI NAMA KOLOM (DALAM BENTUK STRING)
#define Kol_ThnAkademik	CharToString("ThnAkademik")
#define Kol_Semester	CharToString("Semester")
#define Kol_Nilai		CharToString("Nilai")

// KONSTRUKTOR - DESTRUKTOR
TabelPMK	CreateEmptyTabelPMK();
AddressPMK	AllocateRecordPMK(AddressMhs Mhs, AddressMK MK, int Semester, ThnAkademik T, char nilai);
AddressPMK	AllocateRecordPMKAdv(AddressMhs Mhs, AddressMK MK, int Semester, char nilai, ThnAkademik T, AddressPMK next);
void 		DeallocateRecordPMK(RecordPMK *PMK);

// PREDIKAT
void		ChangeRecordPMKContent(AddressPMK PMK, AddressMhs Mhsbaru, AddressMK MKbaru, int semesterBaru, ThnAkademik TBaru, char nilaiBaru);

int 		GetRecordPMKSize(AddressPMK PMK);
/**********************************************************************************
	Menghitung size dari RecordPMK
	I.S. : 	PMK sudah dialokasi
	F.S. : 	return size dari RecordPMK
**********************************************************************************/

// OPERASI
void	 	AddRecordPMK(AddressPMK PMK, TabelPMK *TPMK);
/**********************************************************************************
	Menambahkan PMK ke TPMK di tempat yang tepat
	I.S. : 	PMK sudah dialokasi
	F.S. : 	TPMK berisi PMK dan terurut membesar berdasarkan NIM
**********************************************************************************/ 

void		RemoveRecordPMK(AddressPMK PMK, TabelPMK *TPMK);
/**********************************************************************************
	Membuang PMK dari TPMK 
	I.S. : 	PMK sudah dialokasi
	F.S. : 	TPMK tidak berisi PMK dan PMK tidak didealokasi
**********************************************************************************/

void	 	DestroyRecordPMK(AddressPMK PMK, TabelPMK *TPMK);
/**********************************************************************************
	Mendealokasi PMK dari TPMK.
	I.S. : 	PMK ada di dalam TPMK
	F.S. : 	PMK tidak ada di dalam TPMK. PMK didealokasi.
**********************************************************************************/ 

AddressPMK	SearchRecordPMKByKey(AddressMhs Mhs, AddressMK MK, int semester, ThnAkademik TA, TabelPMK *TPMK);
/**********************************************************************************
	Mencari alamat Record yang memiliki Mhs, MK, TA, dan semester dalam TPMK
	I.S. : 	Sembarang
	F.S. : 	Return address tempat record yang mengandung Key tsb.
			Return NULL jika tidak ditemukan
**********************************************************************************/

AddressPMK	SearchRecordPMK(AddressPMK PMK, TabelPMK *TPMK);
/**********************************************************************************
	Mencari alamat address PMK dalam TPMK
	I.S. : 	Sembarang
	F.S. : 	Return address tempat yang beralamat sama dengan PMK
			Return NULL jika tidak ditemukan
**********************************************************************************/

void		AddOwnerToRecordPMK(AddressPMK PMK, ownerAddress O);
/**********************************************************************************
	Menambah owner ke PMK
	I.S. :	PMK sudah dialokasi, O sudah dialokasi
	F.S. :	O ditambahkan dalam OWNERLIST(PMK)
**********************************************************************************/

void		UpdateIPKdanJmlSKSRecordMhs(AddressMhs Mhs, TabelPMK *TPMK);
/**********************************************************************************
	Mengisi nilai IPK dan JmlSKS dari Mhs berdasarkan TPMK
	I.S. : 	Sembarang
	F.S. : 	Mhs terupdate IPK dan JmlSKS nya
**********************************************************************************/

float		GetNilaiInNumber(AddressPMK PMK);
/**********************************************************************************
	Menerjemahkan nilai dari char menjadi float
	I.S. : 	PMK terdefinisi
	F.S. : 	return 4.0 jika nilai 'A'
			return 3.0 jika nilai 'B'
			return 2.0 jika nilai 'C'
			return 1.0 jika nilai 'D'
			return 0.0 jika nilai 'E'
**********************************************************************************/

int 		CountRecordPMK(TabelPMK T);
/**********************************************************************************
	Menghitung jumlah elemen dari T
	I.S. : 	Sembarang, bisa kosong
	F.S. : 	return jumlah elemen dalam T
**********************************************************************************/ 

int			CountNodeRecordPMK(TabelPMK T, nodeAddress N);
/**********************************************************************************
	Menghitung jumlah elemen di dalam T yang memiliki owner dengan node N
	I.S. : 	Sembarang, bisa kosong
	F.S. : 	return jumlah elemen dalam T yang memiliki owner dengan node N
**********************************************************************************/ 

bool 		EvaluateQueryTabelPMK(AddressPMK PMK, Reader R, bool *query_succeed);


void		DestroyTabelPMK(TabelPMK *T);
/**********************************************************************************
	Mendealokasikan semua elemen dari list
	I.S. : 	Sembarang, list bisa kosong
	F.S. : 	TabelPMK T menjadi kosong
**********************************************************************************/

// OUTPUT - for testing
void		PrintTabelPMK(TabelPMK T);
/**********************************************************************************
	Hanya untuk ngetest
**********************************************************************************/ 

void		PrintTabelPMKHeader(bool showNIM, bool showKode, bool showSemester, bool TA, bool showNilai);
/**********************************************************************************
	Menampilkan Header TabelPMK ke layar.
	Referensi : TabelMhs.h
		
	Lebar kolom :
		NIM			: 15
		Kode		: 15
		Semester	: 10
		TahunAJar	: 15
		Nilai		: 7
**********************************************************************************/ 

void		PrintRecordPMK(AddressPMK PMK, bool showNIM, bool showKode, bool showSemester, bool TA, bool showNilai);
/**********************************************************************************
	Menampilkan MK ke layar.
	Referensi : TabelMhs.h
		
	Lebar kolom :
		NIM			: 15
		Kode		: 15
		Semester	: 10
		TahunAJar	: 15
		Nilai		: 7
**********************************************************************************/ 

#endif

